NAMESPACE_ENTER(CFX)

#include "ReShade/ioFX.cfg"

#if USE_Clarity == 1
//Clarity for ReShade + Framework by Ioxa
//Version 1.0
/* This shader uses the gaussian blur passes from Boulotaur2024's gaussian blur/ bloom, unsharpmask shader which are based
   on the implementation in the article "Efficient Gaussian blur with linear sampling"
   http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ .
   The blend modes are based on algorithms found at http://www.dunnbypaul.net/blends/ , 
   http://www.deepskycolors.com/archive/2010/04/21/formulas-for-Photoshop-blending-modes.html ,
   http://www.simplefilter.de/en/basics/mixmods.html and http://en.wikipedia.org/wiki/Blend_modes . 
   For more info go to http://reshade.me/forum/shader-presentation/529-high-pass-sharpening */ 
#define CoefLuma_HP float3(0.2126, 0.7152, 0.0722)

#if USE_Clarity == 1

#if ClarityTextureFormat == 1
#define CETexFormat RGBA16F
#elif ClarityTextureFormat == 2 
#define CETexFormat RGBA32F
#else
#define CETexFormat RGBA8
#endif

#if ClarityTexScale == 1 
#define CEscale 0.5 
#elif ClarityTexScale == 2 
#define CEscale 0.25 
#else 
#define CEscale 1
#endif

#define cePX_SIZE (RFX_pixelSize*ClarityOffset)

texture ceBlurTex2Dping{ Width = BUFFER_WIDTH*CEscale; Height = BUFFER_HEIGHT*CEscale; Format = CETexFormat; };
texture ceBlurTex2Dpong{ Width = BUFFER_WIDTH*CEscale; Height = BUFFER_HEIGHT*CEscale; Format = CETexFormat; };

sampler2D ceBlurSamplerPing { Texture = ceBlurTex2Dping; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = Clamp; SRGBTexture = FALSE;};
sampler2D ceBlurSamplerPong { Texture = ceBlurTex2Dpong; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = Clamp; SRGBTexture = FALSE;};
#endif

float4 OriginalPixel(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
	float4 color = tex2D(RFX_backbufferColor, texcoord);
	return saturate(color);
}


float4 CEFinal(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
	
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };
		
		float4 color = tex2D(ceBlurSamplerPing, texcoord) * sampleWeights[0];
		
		[loop]
		for(int j = 1; j < 5; ++j) {
			color += tex2D(ceBlurSamplerPing, texcoord + float2(0.0, sampleOffsets[j] * cePX_SIZE.y)) * sampleWeights[j];
			color += tex2D(ceBlurSamplerPing, texcoord - float2(0.0, sampleOffsets[j] * cePX_SIZE.y)) * sampleWeights[j];
		}
		
	float4 orig = tex2D(RFX_backbufferColor, texcoord); //Original Image
	#if ViewBlendIfMask == 1 || ViewMask == 1
	float3 luma = dot(orig.rgb,CoefLuma_HP);
	#else 
	float luma = dot(orig.rgb,CoefLuma_HP);
	#endif
	//luma = (2*(luma - 0.5)*(luma+0.5))+0.5;
	luma = lerp(0,1,smoothstep(0,1,luma));
	float3 chroma = orig.rgb - luma;
		
			float3 sharp = 1 - dot(color.rgb,CoefLuma_HP);
			sharp = (luma+sharp)*0.5;
		
			float3 curve = (2*(sharp - 0.5)*(sharp+0.5))+0.5;
			float3 sharpMin = saturate(lerp(sharp,curve,DarkIntensity));
			sharpMin = min(sharp,sharpMin);
			float3 sharpMax = saturate(lerp(sharp,curve,LightIntensity));
			sharpMax = max(sharp,sharpMax);
			sharp = 0.5*(sharpMin+sharpMax);		
		
		sharp = clamp(sharp,0.50-DarkAmount,0.50+LightAmount);
		
		#if ViewMask == 1
				orig.rgb = sharp;
				luma = sharp;
			#elif ClarityBlendMode == 3
				//Multiply
				sharp = 2 * luma * sharp;
			#elif ClarityBlendMode == 6
				//soft light #2
				sharp = lerp(luma*(sharp+0.5),1-(1-luma)*(1-(sharp-0.5)),step(0.5,sharp));
			#elif ClarityBlendMode == 2
				//overlay
				sharp = lerp(2*luma*sharp, 1.0 - 2*(1.0-luma)*(1.0-sharp), step(0.49,luma));
			#elif ClarityBlendMode == 4
				//Hardlight
				//sharp = luma+2*sharp-1;
				sharp = lerp(2*luma*sharp.rgb, 1.0 - 2*(1.0-luma)*(1.0-sharp), step(0.49,sharp));
			#elif ClarityBlendMode == 1 
				//softlight
				sharp = lerp(2*luma*sharp.rgb + luma*luma*(1.0-2*sharp.rgb), 2*luma*(1.0-sharp)+pow(luma,0.5)*(2*sharp-1.0), step(0.49,sharp.rgb));
			#elif ClarityBlendMode == 5
				//vivid light
				sharp = lerp(2*luma*sharp, luma/(2*(1-sharp)), step(0.5,sharp));
			#elif ClarityBlendMode == 7
				//soft light #3
				sharp = lerp((2*sharp-1)*(luma-pow(luma,2))+luma, ((2*sharp-1)*(pow(luma,0.5)-luma))+luma, step(0.49,sharp));
			#endif
			
					#if BlendIfDark > 0 || BlendIfLight < 255
						#define BlendIfD (BlendIfDark.0/255.0)+0.0001
						#define BlendIfL (BlendIfLight.0/255.0)-0.0001
						float3 mix = luma;
					#if ViewBlendIfMask == 1 
						sharp = float3(1.0,0.0,0.0);
						luma = float3(0.0,0.0,1.0);
						sharp = lerp(luma,sharp,smoothstep(0.0,BlendIfD,mix));
						sharp = lerp(sharp,luma,smoothstep(BlendIfL,1.0,mix));
					#else
						sharp = lerp(luma,sharp,smoothstep(0.0,BlendIfD,mix));
						sharp = lerp(sharp,luma,smoothstep(BlendIfL,1.0,mix));
					#endif
					#endif
					
			orig.rgb = lerp(luma, sharp, ClarityStrength);
		
			#if ViewMask == 1 || ViewBlendIfMask == 1
			#else 
				orig.rgb += chroma;	
			#endif 
			
	//orig.rgb = luma;
	return saturate(orig);
}	

float4 CEBlurX1(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
  
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };

	float4 color = tex2D(ceBlurSamplerPong, texcoord) * sampleWeights[0];
	[loop]
	for(int i = 1; i < 5; ++i) {
		color += tex2D(ceBlurSamplerPong, texcoord + float2(sampleOffsets[i] * RFX_pixelSize.x, 0.0)) * sampleWeights[i];
		color += tex2D(ceBlurSamplerPong, texcoord - float2(sampleOffsets[i] * RFX_pixelSize.x, 0.0)) * sampleWeights[i]; 
	}
	
	return color;
}


float4 CEBlurY1(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
  
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };

	float4 color = tex2D(ceBlurSamplerPing, texcoord) * sampleWeights[0];
	[loop]
	for(int j = 1; j < 5; ++j) {
		color += tex2D(ceBlurSamplerPing, texcoord + float2(0.0, sampleOffsets[j] * RFX_pixelSize.y)) * sampleWeights[j];
		color += tex2D(ceBlurSamplerPing, texcoord - float2(0.0, sampleOffsets[j] * RFX_pixelSize.y)) * sampleWeights[j];
	}

	return color;
}

float4 CEBlurX2(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
  
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };

	float4 color = tex2D(ceBlurSamplerPong, texcoord) * sampleWeights[0];
	[loop]
	for(int i = 1; i < 5; ++i) {
		color += tex2D(ceBlurSamplerPong, texcoord + float2(sampleOffsets[i] * cePX_SIZE.x * 0.5, 0.0)) * sampleWeights[i];
		color += tex2D(ceBlurSamplerPong, texcoord - float2(sampleOffsets[i] * cePX_SIZE.x * 0.5, 0.0)) * sampleWeights[i]; 
	}
	
	return color;
}


float4 CEBlurY2(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
  
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };

	float4 color = tex2D(ceBlurSamplerPing, texcoord) * sampleWeights[0];
	[loop]
	for(int j = 1; j < 5; ++j) {
		color += tex2D(ceBlurSamplerPing, texcoord + float2(0.0, sampleOffsets[j] * cePX_SIZE.y * 0.5)) * sampleWeights[j];
		color += tex2D(ceBlurSamplerPing, texcoord - float2(0.0, sampleOffsets[j] * cePX_SIZE.y * 0.5)) * sampleWeights[j];
	}

	return color;
}

float4 CEBlurX(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
  
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };

	float4 color = tex2D(ceBlurSamplerPong, texcoord) * sampleWeights[0];
	[loop]
	for(int i = 1; i < 5; ++i) {
		color += tex2D(ceBlurSamplerPong, texcoord + float2(sampleOffsets[i] * cePX_SIZE.x, 0.0)) * sampleWeights[i];
		color += tex2D(ceBlurSamplerPong, texcoord - float2(sampleOffsets[i] * cePX_SIZE.x, 0.0)) * sampleWeights[i]; 
	}
	
	return color;
}


float4 CEBlurY(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
  
	float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
	float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };

	float4 color = tex2D(ceBlurSamplerPing, texcoord) * sampleWeights[0];
	[loop]
	for(int j = 1; j < 5; ++j) {
		color += tex2D(ceBlurSamplerPing, texcoord + float2(0.0, sampleOffsets[j] * cePX_SIZE.y)) * sampleWeights[j];
		color += tex2D(ceBlurSamplerPing, texcoord - float2(0.0, sampleOffsets[j] * cePX_SIZE.y)) * sampleWeights[j];
	}

	return color;
}


technique Clarity <bool enabled = RFX_Start_Enabled; int toggle = Clarity_ToggleKey; >
{

	pass G 
	{
		
		VertexShader = RFX_VS_PostProcess;
		PixelShader = OriginalPixel;
		RenderTarget = ceBlurTex2Dpong;
		
	}

	pass H1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX1;
		RenderTarget = ceBlurTex2Dping;
	}

	pass V1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY1;
		RenderTarget = ceBlurTex2Dpong;
	}
	
	pass H1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX2;
		RenderTarget = ceBlurTex2Dping;
	}

	pass V1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY2;
		RenderTarget = ceBlurTex2Dpong;
	}
	
		pass H1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX;
		RenderTarget = ceBlurTex2Dping;
	}
#if CE_MaskQuality >= 1
	pass V1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY;
		RenderTarget = ceBlurTex2Dpong;
	}
	
	pass H2
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX;
		RenderTarget = ceBlurTex2Dping;
	}
#endif	
#if CE_MaskQuality >= 2
	pass V2
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY;
		RenderTarget = ceBlurTex2Dpong;
	}
	
	pass H3
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX;
		RenderTarget = ceBlurTex2Dping;
	}
#endif	
#if CE_MaskQuality >= 3	
	pass V3
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY;
		RenderTarget = ceBlurTex2Dpong;
	}
		
	pass H4
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX;
		RenderTarget = ceBlurTex2Dping;
	}
#endif	
#if CE_MaskQuality >= 4	
	pass V4
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY;
		RenderTarget = ceBlurTex2Dpong;
	}	
	
	pass H5
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX;
		RenderTarget = ceBlurTex2Dping;
	}
#endif	
#if CE_MaskQuality == 5	
	pass V5
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurY;
		RenderTarget = ceBlurTex2Dpong;
	}
	
	pass H6
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEBlurX;
		RenderTarget = ceBlurTex2Dping;
	}
#endif	
	pass ContEnhance
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = CEFinal;
	}


}
#endif

#include "ReShade/ioFX.undef"

NAMESPACE_LEAVE()
